Use @Query('key') for single params, DefaultValuePipe for fallback values, and ParseIntPipe for type conversion. For endpoints with many optional query params, declare a DTO class and use @Query() with no argument combined with a global ValidationPipe with transform: true.
Query string values are always strings — use @Type(() => Number) or ParseIntPipe for numeric conversion.
DefaultValuePipe should come before ParseIntPipe in the pipe chain so the fallback is also converted.
For endpoints with 3+ query params use a DTO class with @Query() — it scales much better.
ValidationPipe with transform: true is required for @Type() decorators on query DTOs to work.
Mark every query DTO field as @IsOptional() — missing query params should never throw 400.